﻿using System;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Web;
using System.Xml.Linq;
using DoveSiButta.Helpers;
using DoveSiButta.Models;
using DoveSiButta.Services;
using DataServicesJSONP;
using System.Data.Services.Client;
using System.Data.Services.Providers;
using System.IO;
using System.Web.Mvc;
using DoveSiButta.Controllers;
using System.Collections.Generic;

namespace DoveSiButta
{
    //[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
    //[JSONPSupportBehavior]
    public partial class ODataServices : DataService<DoveSiButtaEntities>, IServiceProvider
    {
        /*
        IBoxRepository itemsRepository;

      
        // Dependency Injection enabled constructors
        public ODataServices()
            : this(new BoxRepository())
        {
            //_metadata = GetMetadataProvider(typeof(DoveSiButtaEntities));
            //_query = GetQueryProvider(_metadata); 
        }

        public ODataServices(IBoxRepository repository)
        {
            itemsRepository = repository;
        }
        */

        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            //We have thousands of rows so setup server-page
            config.SetEntitySetPageSize("*", 100);
            
            // We're exposing both Dinners and RSVPs for read
            config.SetEntitySetAccessRule("Boxes", EntitySetRights.AllRead |
                                                    EntitySetRights.AllWrite);
            config.SetEntitySetAccessRule("Ratings", EntitySetRights.AllRead |  
                                                    EntitySetRights.AllWrite);
            config.SetEntitySetAccessRule("Pictures", EntitySetRights.AllRead |
                                                    EntitySetRights.AllWrite);
            config.SetServiceOperationAccessRule("ItemsNearMe", ServiceOperationRights.AllRead);
           config.SetServiceOperationAccessRule("ItemsNearMeByCoordinates", ServiceOperationRights.AllRead);
           config.SetServiceOperationAccessRule("FindUpcomingItems", ServiceOperationRights.AllRead);
           config.SetServiceOperationAccessRule("FindAllItems", ServiceOperationRights.AllRead);
            /*
            config.SetServiceOperationAccessRule("CreateNewItem", ServiceOperationRights.All);
            config.SetServiceOperationAccessRule("SetFile", ServiceOperationRights.All);
            config.SetServiceOperationAccessRule("SetFileBase64", ServiceOperationRights.All);
            //config.SetServiceOperationAccessRule("SetBox", ServiceOperationRights.All);
            config.SetServiceOperationAccessRule("GetFile", ServiceOperationRights.AllRead);
            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);*/
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
            //#if DEBUG
            config.UseVerboseErrors = true;
            //#endif
            //config.EnableTypeConversion = true;//GM da provare per problema upload file da iphone
            config.DataServiceBehavior.AcceptProjectionRequests = true; 
            
        }
        /*
        protected override void OnStartProcessingRequest(ProcessRequestArgs args)
        {
            base.OnStartProcessingRequest(args);

            HttpContext context = HttpContext.Current;
            HttpCachePolicy c = context.Response.Cache;
            c.SetCacheability(HttpCacheability.ServerAndPrivate);
            c.SetExpires(context.Timestamp.AddSeconds(30));
            c.VaryByHeaders["Accept"] = true;
            c.VaryByHeaders["Accept-Charset"] = true;
            c.VaryByHeaders["Accept-Encoding"] = true;
            c.VaryByParams["*"] = true;
          //  maxRequestLength=”4194304″
          //maxQueryStringLength=”4194304″
        }
        */
        [WebGet]
        [HandleErrorWithELMAH]
        public IQueryable<Box> FindUpcomingItems()
        {
            BoxRepository itemsRepository = new BoxRepository();
            return itemsRepository.FindUpcomingEvents();
        }

        [WebGet]
        [HandleErrorWithELMAH]
        public IQueryable<Box> FindAllItems()
        {
            BoxRepository itemsRepository = new BoxRepository();
            return itemsRepository.FindAllBoxes();
        }
        
        // http://localhost:60848/Services.svc/ItemsNearMe?placeOrZip='12345'
        [WebGet]
        [HandleErrorWithELMAH]
        public IQueryable<Box> ItemsNearMe(string placeOrZip)
        {
            if (String.IsNullOrEmpty(placeOrZip)) return null; ;

            LatLong location = GeolocationService.PlaceOrZipToLatLong(placeOrZip);
            BoxRepository itemsRepository = new BoxRepository();
            var items = itemsRepository.
                            FindByLocation(location.Lat, location.Long).
                            OrderByDescending(p => p.EventDate);
            return items;
        }
        
        // http://localhost:60848/Services.svc/ItemsNearMeByCoordinates?placeOrZip='12345'
        [WebGet]
        [HandleErrorWithELMAH]
        public IQueryable<Box> ItemsNearMeByCoordinates(float latitude, float longitude)
        {
            if (Math.Round(latitude) == 0.0f || Math.Round(longitude) == 0.0f) return new List<Box>().AsQueryable<Box>() ;

            BoxRepository itemsRepository = new BoxRepository();
            var items = itemsRepository.
                            FindByLocation(latitude, longitude).
                            OrderByDescending(p => p.EventDate);
            return items;
        }
        /*
//        [WebInvoke(Method = "POST")]
//        public void SetSaveStream(
//    int boxID,
//    Stream stream,
//    bool closeStream,
//    DataServiceRequestArgs args
//)
//        {

//        }

        //[WebInvoke(Method="POST")]
        //public int SetBox(Box newbox){
        //    int ret = 0;
        //    itemsRepository.Add(newbox);
        //    itemsRepository.Save();
        //    return ret;
        //}

        [WebGet]
        [HandleErrorWithELMAH]
        public int CreateNewItem(string title, string description, string hostedby, float latitude, float longitude, string address, string country, string boxType, string contactphone, string picture_filename )
        {
            int ret = 0;

            try
            {
                Box box = new Box();
                box.Address = address;
                box.BoxType = boxType;
                box.ContactPhone = contactphone;
                box.Country = country;
                box.Description = description;
                box.EventDate = DateTime.Now;
                box.HostedBy = hostedby;
                box.Latitude = latitude;
                box.Longitude = longitude;
                box.Picture_Filename = picture_filename;
                box.Title = title;
                
                itemsRepository.Add(box);
                itemsRepository.Save();
                
                ret = box.BoxID;
            }
            catch (Exception e)
            {
                Elmah.Error err = new Elmah.Error(e);

                Elmah.ErrorLog el =  Elmah.ErrorLog.GetDefault(HttpContext.Current);
                el.Log(err);
            }

            return ret;
        }

        [WebInvoke(Method = "POST", UriTemplate="SetFile/")]
        //[WebGet]
        [HandleErrorWithELMAH]
        public int SetFile(int itemID, byte[] file)
        {
            int ret = 0;
            try
            {
                //Dinner d = itemsRepository.GetDinner(itemID);
                //d.Picture_Filename = System.IO.Path.GetRandomFileName() + ".jpg";
      
                Box d = itemsRepository.GetBox(itemID);
                DateTime time = DateTime.Now;
                string format = "yyyyMMdd_hhmmss";
                d.Picture_Filename = time.ToString(format) + System.IO.Path.GetRandomFileName() + ".jpg";
           
                //Per scrivere su disco
                string picturesFolder = "Pictures/";
                string baseAppPath = HttpContext.Current.Request.ApplicationPath;
                string picturesPath = baseAppPath + picturesFolder;
                string filePath = Path.Combine(HttpContext.Current.Server.MapPath(picturesPath)
                    , d.Picture_Filename);
                FileStream fs = new FileStream(filePath, FileMode.Create);
                fs.Write(file, 0, file.Length);
                fs.Close();
                ret = 1;
            }
            catch (Exception e)
            {
                ret = -1;
                Elmah.Error err = new Elmah.Error(e);

                Elmah.ErrorLog el = Elmah.ErrorLog.GetDefault(HttpContext.Current);
                el.Log(err);
            }
            return ret;

        }

       //[WebInvoke( Method = "POST")]
        [WebGet]
       [HandleErrorWithELMAH]
        public int SetFileBase64(int itemID, string fileBase64)
        {
            int ret = 0;
            try
            {
                byte[] encodedDataAsBytes = System.Convert.FromBase64String(fileBase64);

                Box d = itemsRepository.GetBox(itemID);
                DateTime time = DateTime.Now;
                string format = "yyyyMMdd_hhmmss";
                d.Picture_Filename = time.ToString(format) + System.IO.Path.GetRandomFileName() + ".jpg";
                //d.Picture_File = encodedDataAsBytes;
                //Per scrivere su disco
                string picturesFolder = "Pictures/";
                string baseAppPath = HttpContext.Current.Request.ApplicationPath;
                string picturesPath = baseAppPath + picturesFolder;
                string filePath = Path.Combine(HttpContext.Current.Server.MapPath(picturesPath)
                    , d.Picture_Filename);
                FileStream fs = new FileStream(filePath, FileMode.Create);
                fs.Write(encodedDataAsBytes, 0, encodedDataAsBytes.Length);
                fs.Close();

                ret = 1;
            }
            catch (Exception e)
            {
                ret = -1;
                Elmah.Error err = new Elmah.Error(e);

                Elmah.ErrorLog el = Elmah.ErrorLog.GetDefault(HttpContext.Current);
                el.Log(err);
            }
            return ret;

        }

        [WebGet]
        public string GetFile(int itemID)
        {
            //TODO: restituire il nome del file
            //Al momento ritorna <GetFile xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">F:\sitesroot\0\Pictures</GetFile>
            string ritorno = "";
            try
            {
                Box d = itemsRepository.GetBox(itemID);
                if (d != null && d.Picture_Filename != "")
                {
                    //string picturesFolder = "Pictures/";
                    //string baseAppPath = HttpContext.Current.Request.ApplicationPath;
                    //string picturesPath = baseAppPath + picturesFolder;
                    //string filePath = Path.Combine(HttpContext.Current.Server.MapPath(picturesPath)
                    //    , d.Picture_Filename);  //TOOD: Verificare che trovi il path //GM
                    //FileStream fs = new FileStream(filePath, FileMode.Create);
                    //fs.Write(d.Picture_File, 0, d.Picture_File.Length);
                    //fs.Close();
                    //string externalPath = picturesPath + d.Picture_Filename;
                    //ritorno = externalPath;
                    ritorno = d.Picture_Filename;
                }
            }
            catch
            {

            }

            return ritorno;
        }

        [WebGet]
        public int Login(string username, string password)
        {
            AccountController ac = new AccountController();
            if (ac.ValidateLogOn(username, password))
            {
                return 1;
            }
            else
            {
                return -1;
            }

        }
        */
        /*
        [HasStream]
        public void UploadFile(byte[] file)
        {
            // Set the file stream as the source of binary stream 
            // to send to the data service. The Slug header is the file name and
            // the content type is determined from the file extension. 
            // A value of 'true' means that the stream is closed by the client when 
            // the upload is complete.
            DataServiceContext context = new DataServiceContext();
            HttpCachePolicy c = context.Response.Cache;
            context.SetSaveStream(dinner, file, true,
                dinner.Picture_File, dinner.Picture_Filename);
        }
        */


    }

            // We must override CreateDataSource to manually return an ObjectContext,
        // otherwise the runtime tries to use the built-in reflection provider instead of 
        // the Entity Framework provider.
 

    //http://msdn.microsoft.com/en-us/library/ee960144.aspx
    public partial class ODataServices
    {


        public object GetService(Type serviceType)
        {
            //if (serviceType == typeof(IDataServiceUpdateProvider) || serviceType == typeof(IDataServiceQueryProvider))
            //{
            //    return this;
            //}
            //else 
                if (serviceType == typeof(IDataServiceStreamProvider))
            {
                // Return the stream provider to the data service.
                return new DoveSiButtaStreamProvider(this.CurrentDataSource);
            }
            else
            {
                return null;
            }
        }

    }

}
